home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / TRANSFRM.ZIP / TRANSFRM.TXT
Encoding:
Text File  |  1996-04-26  |  4.7 KB  |  260 lines

  1.  
  2.               
  3.  
  4.                     Perspective Transforms
  5.  
  6.                
  7.  
  8.  
  9.         By Andre Yew (andrey@gluttony.ugcs.caltech.edu)
  10.  
  11.  
  12.  
  13.  
  14.     This is how I learned perspective transforms --- it was
  15.  
  16. intuitive and understandable to me, so perhaps it'll be to
  17.  
  18. others as well.  It does require knowledge of matrix math
  19.  
  20. and homogeneous coordinates.  IMO, if you want to write a
  21.  
  22. serious renderer, you need to know both.
  23.  
  24.  
  25.    First, let's look at what we're trying to do:
  26.  
  27.                S (screen)
  28.  
  29.                |    * P (y, z)
  30.  
  31.                |   /|
  32.  
  33.                |  / |
  34.  
  35.                | /  |
  36.  
  37.                |/   |
  38.  
  39.                * R  |
  40.  
  41.              / |    |
  42.  
  43.             /  |    |
  44.  
  45.            /   |    |
  46.  
  47.    E (eye)/    |    | W
  48.  
  49. ---------*-----|----*-------------
  50.  
  51.          <- d -><-z->
  52.  
  53.  
  54.    E is the eye, P is the point we're trying to project, and
  55.  
  56. R is its projected position on the screen S (this is the point
  57.  
  58. you want to draw on your monitor).  Z goes into the monitor (left-
  59.  
  60. handed coordinates), with X and Y being the width and height of the
  61.  
  62. screen.  So let's find where R is:
  63.  
  64.  
  65.     R = (xs, ys)
  66.  
  67.  
  68.     Using similar triangles (ERS and EPW)
  69.  
  70.  
  71.     xs/d = x/(z + d)
  72.  
  73.     ys/d = y/(z + d)
  74.  
  75.     (Use similar triangles to determine this)
  76.  
  77.  
  78.     So,
  79.  
  80.  
  81.     xs = x*d/(z + d)
  82.  
  83.     ys = y*d/(z + d)
  84.  
  85.  
  86.     Express this homogeneously:
  87.  
  88.  
  89.     R = (xs, ys, zs, ws).
  90.  
  91.  
  92.     Make xs = x*d
  93.  
  94.          ys = y*d
  95.  
  96.          zs = 0 (the screen is a flat plane)
  97.  
  98.          ws = z + d
  99.  
  100.  
  101.     and express this as a vector transformed by a matrix:
  102.  
  103.  
  104.     [x y z 1][ d 0 0 0 ]
  105.  
  106.              [ 0 d 0 0 ]    =  R
  107.  
  108.              [ 0 0 0 1 ]
  109.  
  110.              [ 0 0 0 d ]
  111.  
  112.  
  113.     The matrix on the right side can be called a perspective transform.
  114.  
  115. But we aren't done yet.  See the zero in the 3rd column, 3rd row of
  116.  
  117. the matrix?  Make it a 1 so we retain the z value (perhaps for some
  118.  
  119. kind of Z-buffer).  Also, this isn't exactly what we want since we'd
  120.  
  121. also like to have the eye at the origin and we'd like to specify some
  122.  
  123. kind of field-of-view.  So, let's translate the matrix (we'll call
  124.  
  125. it M) by -d to move the eye to the origin:
  126.  
  127.  
  128.     [ 1 0 0  0 ][ d 0 0 0 ]
  129.  
  130.     [ 0 1 0  0 ][ 0 d 0 0 ]
  131.  
  132.     [ 0 0 1  0 ][ 0 0 1 1 ]  <--- Remember, we put a 1 in (3,3) to
  133.  
  134.     [ 0 0 -d 1 ][ 0 0 0 d ]       retain the z part of the vector.
  135.  
  136.  
  137.     And we get:
  138.  
  139.  
  140.     [ d 0 0  0 ]
  141.  
  142.     [ 0 d 0  0 ]
  143.  
  144.     [ 0 0 1  1 ]
  145.  
  146.     [ 0 0 -d 0 ]
  147.  
  148.  
  149.     Now parametrize d by the angle PEW, which is half the field-of-view
  150.  
  151. (FOV/2).  So we now want to pick a d such that ys = 1 always and we get
  152.  
  153. a nice relationship:
  154.  
  155.  
  156.     d = cot( FOV/2 )
  157.  
  158.  
  159.     Or, to put it another way, using this formula, ys = 1 always.
  160.  
  161.  
  162.     Replace all the d's in the last perspective matrix and multiply
  163.  
  164. through by sin's:
  165.  
  166.  
  167.     [ cos 0   0    0   ]
  168.  
  169.     [ 0   cos 0    0   ]
  170.  
  171.     [ 0   0   sin  sin ]
  172.  
  173.     [ 0   0   -cos 0   ]
  174.  
  175.  
  176.     With all the trig functions taking FOV/2 as their arguments.
  177.  
  178. Let's refine this a little further and add near and far Z-clipping
  179.  
  180. planes.  Look at the lower right 2x2 matrix:
  181.  
  182.  
  183.    [ sin sin ]
  184.  
  185.    [-cos 0   ]
  186.  
  187.  
  188.    and replace the first column by a and b:
  189.  
  190.  
  191.    [ a sin ]
  192.  
  193.    [ b 0   ]
  194.  
  195.    [ b 0   ]
  196.  
  197.  
  198.    Transform out near and far boundaries represented homogeneously
  199.  
  200. as (zn, 1), (zf, 1), respectively and we get:
  201.  
  202.  
  203.    (zn*a + b, zn*sin) and (zf*a + b, zf*sin).
  204.  
  205.  
  206.    We want the transformed boundaries to map to 0 and 1, respectively,
  207.  
  208. so divide out the homogeneous parts to get normal coordinates and equate:
  209.  
  210.  
  211.     (zn*a + b)/(zn*sin) = 0 (near plane)
  212.  
  213.     (zf*a + b)/(zf*sin) = 1 (far plane)
  214.  
  215.  
  216.    Now solve for a and b and we get:
  217.  
  218.  
  219.    a = (zf*sin)/(zf - zn)
  220.  
  221.      = sin/(1 - zn/zf)
  222.  
  223.    b = -a*zn
  224.  
  225.    b = -a*zn
  226.  
  227.  
  228.    At last we have the familiar looking perspective transform matrix:
  229.  
  230.  
  231.    [ cos( FOV/2 ) 0                        0            0 ]
  232.  
  233.    [ 0            cos( FOV/2 )             0            0 ]
  234.  
  235.    [ 0            0 sin( FOV/2 )/(1 - zn/zf) sin( FOV/2 ) ]
  236.  
  237.    [ 0            0                    -a*zn            0 ]
  238.  
  239.  
  240.    There are some pretty neat properties of the matrix.  Perhaps
  241.  
  242. the most interesting is how it transforms objects that go through
  243.  
  244. the camera plane, and how coupled with a clipper set up the right
  245.  
  246. way, it does everything correctly.  What's interesting about this
  247.  
  248. is how it warps space into something called Moebius space, which
  249.  
  250. is kind of like a fortune-cookie except the folds pass through
  251.  
  252. each other to connect the lower folds --- you really have to see
  253.  
  254. it to understand it.  Try feeding it some vectors that go off to
  255.  
  256. infinity in various directions (ws = 0) and see where they come
  257.  
  258. out.
  259.  
  260.